#pragma once
#include "pch.h"
#include "SNES/DSP/Dsp.h"

class DspInterpolation
{
private:
	static constexpr int16_t const gauss[512] = {
			0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
			1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
			2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
			6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
		  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
		  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
		  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
		  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
		  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
		  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
		 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
		 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
		 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
		 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
		 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
		 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
		 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
		 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
		 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
		 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
		 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
		 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
		 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
		 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
		 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
		1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
		1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
		1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
		1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
		1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
		1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
		1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
	};

public:
	static int16_t Gauss(int32_t interpolationPos, int16_t* samples, uint8_t bufferPos)
	{
		uint8_t pos = (interpolationPos >> 12) + bufferPos;
		uint8_t offset = (interpolationPos >> 4) & 0xFF;
		
		//"The above 3 wrap at 15 bits signed. The last is added to that, and is clamped rather than wrapped.
		int32_t out = (int16_t)(
			((gauss[255 - offset] * (int32_t)samples[pos % 12]) >> 11) +
			((gauss[511 - offset] * (int32_t)samples[(pos + 1) % 12]) >> 11) +
			((gauss[256 + offset] * (int32_t)samples[(pos + 2) % 12]) >> 11)
		) + ((gauss[offset] * (int32_t)samples[(pos + 3) % 12]) >> 11);

		return Dsp::Clamp16(out) & ~0x01;
	}

	static int16_t Cubic(int32_t interpolationPos, int16_t* samples, uint8_t bufferPos)
	{
		uint8_t pos = (interpolationPos >> 12) + bufferPos;

		float v0 = samples[pos % 12] / 32768.0f;
		float v1 = samples[(pos + 1) % 12] / 32768.0f;
		float v2 = samples[(pos + 2) % 12] / 32768.0f;
		float v3 = samples[(pos + 3) % 12] / 32768.0f;

		float a = (v3 - v2) - (v0 - v1);
		float b = (v0 - v1) - a;
		float c = v2 - v0;
		float d = v1;

		float ratio = (float)(interpolationPos & 0xFFF) / 0x1000;

		return Dsp::Clamp16((d + ratio * (c + ratio * (b + ratio * a))) * 32768);
	}
	
	static int16_t Sinc(int32_t interpolationPos, int16_t* samples, uint8_t bufferPos)
	{
		uint8_t pos = (interpolationPos >> 12) + bufferPos;
		uint16_t offset = ((interpolationPos >> 4) & 0xFF) * 8;

		return Dsp::Clamp16((
			(_sincTable[offset + 0] * samples[(pos + 0) % 12]) +
			(_sincTable[offset + 1] * samples[(pos + 1) % 12]) +
			(_sincTable[offset + 2] * samples[(pos + 2) % 12]) +
			(_sincTable[offset + 3] * samples[(pos + 3) % 12]) +
			(_sincTable[offset + 4] * samples[(pos + 4) % 12]) +
			(_sincTable[offset + 5] * samples[(pos + 5) % 12]) +
			(_sincTable[offset + 6] * samples[(pos + 6) % 12]) +
			(_sincTable[offset + 7] * samples[(pos + 7) % 12])
		) >> 14);
	}

private:
	/*
	* Table generated via the following Python script
	  (Original source: https://tomroelandts.com/articles/how-to-create-a-simple-low-pass-filter)

	 ----
		from __future__ import division
		import numpy as np
 
		fc = 0.5  # Cutoff frequency as a fraction of the sampling rate (in (0, 0.5)).
		N = 10
		n = np.arange(N)
 
		for x in range(0, 256): 
			# Compute sinc filter.
			h = np.sinc(2 * fc * (n - 4 - (x / 255.0)))

			# Compute Blackman window.
			w = 0.42 - 0.5 * np.cos(2 * np.pi * n / (N - 1)) + \
				0.08 * np.cos(4 * np.pi * n / (N - 1))

			# Multiply sinc filter by window.
			h = h * w

			# Normalize to get unity gain.
			h = h / np.sum(h) * 16384

			print(h.astype(int))
		----
	*/
	static constexpr int16_t const _sincTable[2048] = {
		0, 0, 0, 16384, 0, 0, 0, 0,
		-1, 8, -42, 16370, 64, -21, 5, 0,
		-2, 17, -84, 16356, 129, -42, 11, -1,
		-3, 25, -125, 16341, 194, -64, 17, -2,
		-4, 34, -167, 16326, 260, -85, 23, -3,
		-5, 42, -207, 16310, 326, -106, 29, -4,
		-6, 51, -248, 16293, 392, -128, 34, -5,
		-7, 59, -288, 16276, 459, -150, 40, -6,
		-8, 68, -327, 16257, 526, -171, 46, -6,
		-10, 76, -366, 16238, 594, -193, 52, -7,
		-11, 84, -405, 16219, 662, -214, 58, -8,
		-12, 92, -443, 16198, 730, -236, 64, -9,
		-13, 100, -481, 16177, 798, -258, 69, -10,
		-14, 108, -519, 16156, 867, -279, 75, -11,
		-15, 116, -556, 16133, 937, -301, 81, -12,
		-16, 124, -592, 16110, 1006, -323, 87, -12,
		-17, 132, -629, 16086, 1076, -345, 93, -13,
		-18, 140, -664, 16062, 1147, -366, 99, -14,
		-19, 148, -700, 16037, 1218, -388, 104, -15,
		-20, 155, -735, 16011, 1289, -410, 110, -16,
		-21, 163, -770, 15984, 1360, -432, 116, -17,
		-22, 171, -804, 15957, 1432, -453, 122, -17,
		-23, 178, -838, 15929, 1504, -475, 127, -18,
		-24, 186, -871, 15901, 1576, -497, 133, -19,
		-25, 193, -904, 15871, 1649, -519, 139, -20,
		-26, 200, -936, 15841, 1721, -540, 145, -21,
		-27, 208, -969, 15811, 1795, -562, 150, -22,
		-28, 215, -1000, 15780, 1868, -584, 156, -22,
		-29, 222, -1032, 15748, 1942, -605, 162, -23,
		-30, 229, -1062, 15715, 2016, -627, 167, -24,
		-31, 236, -1093, 15682, 2091, -649, 173, -25,
		-32, 243, -1123, 15648, 2165, -670, 179, -26,
		-33, 250, -1153, 15614, 2240, -692, 184, -27,
		-34, 256, -1182, 15579, 2315, -713, 190, -27,
		-35, 263, -1211, 15543, 2391, -735, 196, -28,
		-36, 270, -1239, 15507, 2467, -756, 201, -29,
		-37, 276, -1267, 15470, 2543, -778, 207, -30,
		-38, 283, -1295, 15432, 2619, -799, 212, -31,
		-38, 289, -1322, 15394, 2695, -820, 218, -31,
		-39, 295, -1349, 15355, 2772, -842, 223, -32,
		-40, 302, -1375, 15316, 2849, -863, 229, -33,
		-41, 308, -1401, 15276, 2926, -884, 234, -34,
		-42, 314, -1427, 15235, 3004, -905, 240, -34,
		-43, 320, -1452, 15194, 3081, -926, 245, -35,
		-44, 326, -1476, 15152, 3159, -947, 250, -36,
		-44, 332, -1501, 15109, 3237, -968, 256, -37,
		-45, 338, -1525, 15066, 3316, -989, 261, -38,
		-46, 343, -1548, 15022, 3394, -1010, 266, -38,
		-47, 349, -1571, 14978, 3473, -1030, 272, -39,
		-48, 355, -1594, 14933, 3552, -1051, 277, -40,
		-48, 360, -1616, 14888, 3631, -1071, 282, -41,
		-49, 366, -1638, 14842, 3710, -1092, 287, -41,
		-50, 371, -1659, 14795, 3789, -1112, 292, -42,
		-51, 376, -1680, 14748, 3869, -1132, 297, -43,
		-51, 381, -1701, 14700, 3949, -1153, 302, -43,
		-52, 386, -1721, 14652, 4029, -1173, 307, -44,
		-53, 391, -1741, 14603, 4109, -1193, 312, -45,
		-53, 396, -1761, 14553, 4189, -1212, 317, -46,
		-54, 401, -1780, 14503, 4270, -1232, 322, -46,
		-55, 406, -1798, 14453, 4350, -1252, 327, -47,
		-56, 411, -1817, 14402, 4431, -1271, 332, -48,
		-56, 415, -1834, 14350, 4512, -1291, 337, -48,
		-57, 420, -1852, 14298, 4593, -1310, 342, -49,
		-57, 424, -1869, 14245, 4674, -1329, 346, -50,
		-58, 429, -1885, 14192, 4755, -1348, 351, -50,
		-59, 433, -1902, 14138, 4836, -1367, 356, -51,
		-59, 437, -1918, 14084, 4918, -1386, 360, -52,
		-60, 441, -1933, 14029, 4999, -1405, 365, -52,
		-61, 445, -1948, 13973, 5081, -1423, 369, -53,
		-61, 449, -1963, 13917, 5163, -1442, 374, -54,
		-62, 453, -1977, 13861, 5244, -1460, 378, -54,
		-62, 457, -1991, 13804, 5326, -1478, 383, -55,
		-63, 461, -2004, 13747, 5408, -1496, 387, -55,
		-63, 464, -2018, 13689, 5490, -1514, 391, -56,
		-64, 468, -2030, 13631, 5572, -1532, 395, -57,
		-64, 471, -2043, 13572, 5655, -1549, 400, -57,
		-65, 475, -2055, 13512, 5737, -1567, 404, -58,
		-65, 478, -2066, 13453, 5819, -1584, 408, -58,
		-66, 481, -2077, 13392, 5901, -1601, 412, -59,
		-66, 485, -2088, 13332, 5984, -1618, 416, -59,
		-67, 488, -2099, 13270, 6066, -1635, 420, -60,
		-67, 491, -2109, 13209, 6149, -1651, 424, -60,
		-68, 493, -2118, 13147, 6231, -1668, 428, -61,
		-68, 496, -2128, 13084, 6314, -1684, 431, -61,
		-68, 499, -2137, 13021, 6396, -1700, 435, -62,
		-69, 502, -2145, 12958, 6479, -1716, 439, -63,
		-69, 504, -2153, 12894, 6561, -1732, 443, -63,
		-70, 507, -2161, 12829, 6644, -1747, 446, -63,
		-70, 509, -2169, 12765, 6726, -1763, 450, -64,
		-70, 511, -2176, 12699, 6809, -1778, 453, -64,
		-71, 514, -2183, 12634, 6891, -1793, 456, -65,
		-71, 516, -2189, 12568, 6973, -1808, 460, -65,
		-71, 518, -2195, 12501, 7056, -1822, 463, -66,
		-72, 520, -2201, 12435, 7138, -1836, 466, -66,
		-72, 522, -2206, 12367, 7221, -1851, 469, -67,
		-72, 523, -2211, 12300, 7303, -1865, 473, -67,
		-72, 525, -2216, 12232, 7385, -1878, 476, -67,
		-73, 527, -2220, 12164, 7467, -1892, 479, -68,
		-73, 528, -2224, 12095, 7549, -1905, 482, -68,
		-73, 530, -2227, 12026, 7631, -1918, 484, -69,
		-73, 531, -2230, 11956, 7713, -1931, 487, -69,
		-74, 532, -2233, 11886, 7795, -1944, 490, -69,
		-74, 534, -2236, 11816, 7877, -1956, 493, -70,
		-74, 535, -2238, 11745, 7959, -1968, 495, -70,
		-74, 536, -2240, 11675, 8041, -1980, 498, -70,
		-74, 537, -2241, 11603, 8122, -1992, 500, -71,
		-75, 538, -2242, 11532, 8204, -2004, 503, -71,
		-75, 539, -2243, 11460, 8285, -2015, 505, -71,
		-75, 539, -2244, 11387, 8366, -2026, 507, -72,
		-75, 540, -2244, 11315, 8447, -2037, 509, -72,
		-75, 541, -2244, 11242, 8528, -2047, 512, -72,
		-75, 541, -2243, 11169, 8609, -2058, 514, -72,
		-75, 541, -2242, 11095, 8690, -2068, 516, -73,
		-75, 542, -2241, 11021, 8770, -2077, 518, -73,
		-75, 542, -2240, 10947, 8851, -2087, 520, -73,
		-75, 542, -2238, 10873, 8931, -2096, 521, -73,
		-76, 542, -2236, 10798, 9011, -2105, 523, -74,
		-76, 542, -2233, 10723, 9091, -2114, 525, -74,
		-76, 542, -2231, 10648, 9171, -2123, 526, -74,
		-76, 542, -2228, 10572, 9250, -2131, 528, -74,
		-76, 542, -2224, 10496, 9330, -2139, 529, -74,
		-76, 542, -2221, 10420, 9409, -2146, 531, -75,
		-76, 541, -2217, 10344, 9488, -2154, 532, -75,
		-76, 541, -2213, 10267, 9567, -2161, 533, -75,
		-76, 540, -2208, 10190, 9646, -2168, 534, -75,
		-75, 540, -2203, 10113, 9724, -2174, 535, -75,
		-75, 539, -2198, 10036, 9802, -2181, 536, -75,
		-75, 538, -2193, 9958, 9880, -2187, 537, -75,
		-75, 537, -2187, 9880, 9958, -2193, 538, -75,
		-75, 536, -2181, 9802, 10036, -2198, 539, -75,
		-75, 535, -2174, 9724, 10113, -2203, 540, -75,
		-75, 534, -2168, 9646, 10190, -2208, 540, -76,
		-75, 533, -2161, 9567, 10267, -2213, 541, -76,
		-75, 532, -2154, 9488, 10344, -2217, 541, -76,
		-75, 531, -2146, 9409, 10420, -2221, 542, -76,
		-74, 529, -2139, 9330, 10496, -2224, 542, -76,
		-74, 528, -2131, 9250, 10572, -2228, 542, -76,
		-74, 526, -2123, 9171, 10648, -2231, 542, -76,
		-74, 525, -2114, 9091, 10723, -2233, 542, -76,
		-74, 523, -2105, 9011, 10798, -2236, 542, -76,
		-73, 521, -2096, 8931, 10873, -2238, 542, -75,
		-73, 520, -2087, 8851, 10947, -2240, 542, -75,
		-73, 518, -2077, 8770, 11021, -2241, 542, -75,
		-73, 516, -2068, 8690, 11095, -2242, 541, -75,
		-72, 514, -2058, 8609, 11169, -2243, 541, -75,
		-72, 512, -2047, 8528, 11242, -2244, 541, -75,
		-72, 509, -2037, 8447, 11315, -2244, 540, -75,
		-72, 507, -2026, 8366, 11387, -2244, 539, -75,
		-71, 505, -2015, 8285, 11460, -2243, 539, -75,
		-71, 503, -2004, 8204, 11532, -2242, 538, -75,
		-71, 500, -1992, 8122, 11603, -2241, 537, -74,
		-70, 498, -1980, 8041, 11675, -2240, 536, -74,
		-70, 495, -1968, 7959, 11745, -2238, 535, -74,
		-70, 493, -1956, 7877, 11816, -2236, 534, -74,
		-69, 490, -1944, 7795, 11886, -2233, 532, -74,
		-69, 487, -1931, 7713, 11956, -2230, 531, -73,
		-69, 484, -1918, 7631, 12026, -2227, 530, -73,
		-68, 482, -1905, 7549, 12095, -2224, 528, -73,
		-68, 479, -1892, 7467, 12164, -2220, 527, -73,
		-67, 476, -1878, 7385, 12232, -2216, 525, -72,
		-67, 473, -1865, 7303, 12300, -2211, 523, -72,
		-67, 469, -1851, 7221, 12367, -2206, 522, -72,
		-66, 466, -1836, 7138, 12435, -2201, 520, -72,
		-66, 463, -1822, 7056, 12501, -2195, 518, -71,
		-65, 460, -1808, 6973, 12568, -2189, 516, -71,
		-65, 456, -1793, 6891, 12634, -2183, 514, -71,
		-64, 453, -1778, 6809, 12699, -2176, 511, -70,
		-64, 450, -1763, 6726, 12765, -2169, 509, -70,
		-63, 446, -1747, 6644, 12829, -2161, 507, -70,
		-63, 443, -1732, 6561, 12894, -2153, 504, -69,
		-63, 439, -1716, 6479, 12958, -2145, 502, -69,
		-62, 435, -1700, 6396, 13021, -2137, 499, -68,
		-61, 431, -1684, 6314, 13084, -2128, 496, -68,
		-61, 428, -1668, 6231, 13147, -2118, 493, -68,
		-60, 424, -1651, 6149, 13209, -2109, 491, -67,
		-60, 420, -1635, 6066, 13270, -2099, 488, -67,
		-59, 416, -1618, 5984, 13332, -2088, 485, -66,
		-59, 412, -1601, 5901, 13392, -2077, 481, -66,
		-58, 408, -1584, 5819, 13453, -2066, 478, -65,
		-58, 404, -1567, 5737, 13512, -2055, 475, -65,
		-57, 400, -1549, 5655, 13572, -2043, 471, -64,
		-57, 395, -1532, 5572, 13631, -2030, 468, -64,
		-56, 391, -1514, 5490, 13689, -2018, 464, -63,
		-55, 387, -1496, 5408, 13747, -2004, 461, -63,
		-55, 383, -1478, 5326, 13804, -1991, 457, -62,
		-54, 378, -1460, 5244, 13861, -1977, 453, -62,
		-54, 374, -1442, 5163, 13917, -1963, 449, -61,
		-53, 369, -1423, 5081, 13973, -1948, 445, -61,
		-52, 365, -1405, 4999, 14029, -1933, 441, -60,
		-52, 360, -1386, 4918, 14084, -1918, 437, -59,
		-51, 356, -1367, 4836, 14138, -1902, 433, -59,
		-50, 351, -1348, 4755, 14192, -1885, 429, -58,
		-50, 346, -1329, 4674, 14245, -1869, 424, -57,
		-49, 342, -1310, 4593, 14298, -1852, 420, -57,
		-48, 337, -1291, 4512, 14350, -1834, 415, -56,
		-48, 332, -1271, 4431, 14402, -1817, 411, -56,
		-47, 327, -1252, 4350, 14453, -1798, 406, -55,
		-46, 322, -1232, 4270, 14503, -1780, 401, -54,
		-46, 317, -1212, 4189, 14553, -1761, 396, -53,
		-45, 312, -1193, 4109, 14603, -1741, 391, -53,
		-44, 307, -1173, 4029, 14652, -1721, 386, -52,
		-43, 302, -1153, 3949, 14700, -1701, 381, -51,
		-43, 297, -1132, 3869, 14748, -1680, 376, -51,
		-42, 292, -1112, 3789, 14795, -1659, 371, -50,
		-41, 287, -1092, 3710, 14842, -1638, 366, -49,
		-41, 282, -1071, 3631, 14888, -1616, 360, -48,
		-40, 277, -1051, 3552, 14933, -1594, 355, -48,
		-39, 272, -1030, 3473, 14978, -1571, 349, -47,
		-38, 266, -1010, 3394, 15022, -1548, 343, -46,
		-38, 261, -989, 3316, 15066, -1525, 338, -45,
		-37, 256, -968, 3237, 15109, -1501, 332, -44,
		-36, 250, -947, 3159, 15152, -1476, 326, -44,
		-35, 245, -926, 3081, 15194, -1452, 320, -43,
		-34, 240, -905, 3004, 15235, -1427, 314, -42,
		-34, 234, -884, 2926, 15276, -1401, 308, -41,
		-33, 229, -863, 2849, 15316, -1375, 302, -40,
		-32, 223, -842, 2772, 15355, -1349, 295, -39,
		-31, 218, -820, 2695, 15394, -1322, 289, -38,
		-31, 212, -799, 2619, 15432, -1295, 283, -38,
		-30, 207, -778, 2543, 15470, -1267, 276, -37,
		-29, 201, -756, 2467, 15507, -1239, 270, -36,
		-28, 196, -735, 2391, 15543, -1211, 263, -35,
		-27, 190, -713, 2315, 15579, -1182, 256, -34,
		-27, 184, -692, 2240, 15614, -1153, 250, -33,
		-26, 179, -670, 2165, 15648, -1123, 243, -32,
		-25, 173, -649, 2091, 15682, -1093, 236, -31,
		-24, 167, -627, 2016, 15715, -1062, 229, -30,
		-23, 162, -605, 1942, 15748, -1032, 222, -29,
		-22, 156, -584, 1868, 15780, -1000, 215, -28,
		-22, 150, -562, 1795, 15811, -969, 208, -27,
		-21, 145, -540, 1721, 15841, -936, 200, -26,
		-20, 139, -519, 1649, 15871, -904, 193, -25,
		-19, 133, -497, 1576, 15901, -871, 186, -24,
		-18, 127, -475, 1504, 15929, -838, 178, -23,
		-17, 122, -453, 1432, 15957, -804, 171, -22,
		-17, 116, -432, 1360, 15984, -770, 163, -21,
		-16, 110, -410, 1289, 16011, -735, 155, -20,
		-15, 104, -388, 1218, 16037, -700, 148, -19,
		-14, 99, -366, 1147, 16062, -664, 140, -18,
		-13, 93, -345, 1076, 16086, -629, 132, -17,
		-12, 87, -323, 1006, 16110, -592, 124, -16,
		-12, 81, -301, 937, 16133, -556, 116, -15,
		-11, 75, -279, 867, 16156, -519, 108, -14,
		-10, 69, -258, 798, 16177, -481, 100, -13,
		-9, 64, -236, 730, 16198, -443, 92, -12,
		-8, 58, -214, 662, 16219, -405, 84, -11,
		-7, 52, -193, 594, 16238, -366, 76, -10,
		-6, 46, -171, 526, 16257, -327, 68, -8,
		-6, 40, -150, 459, 16276, -288, 59, -7,
		-5, 34, -128, 392, 16293, -248, 51, -6,
		-4, 29, -106, 326, 16310, -207, 42, -5,
		-3, 23, -85, 260, 16326, -167, 34, -4,
		-2, 17, -64, 194, 16341, -125, 25, -3,
		-1, 11, -42, 129, 16356, -84, 17, -2,
		0, 5, -21, 64, 16370, -42, 8, -1,
		0, 0, 0, 0, 16384, 0, 0, 0,
	};
};
